﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace TrainTicket
{
    public partial class Form1 : Form
    {
        static Dictionary<string,string> SessionCookies = new Dictionary<string,string> ();
        public Form1()
        {
            InitializeComponent();
            usernameTB.Text = "zjh201008";
            pswTB.Text = "";
            GetCookies();



            //ParseJson();
        }

        void ParseJson()
        {
            StreamReader sr = new StreamReader("c.txt");
            string str = sr.ReadToEnd();
            sr.Close();
            var exeRet = JsonConvert.DeserializeObject<QueryTicketResult>(str);

        }

        private void button1_Click(object sender, EventArgs e)
        {
            //SessionId = Guid.NewGuid().ToString().Replace("-", "").ToUpper();
            Stream resopnseStream;
            // Initialize a request.
            //string iniUri = @"https://kyfw.12306.cn/otn/login/init";
            //GetRequest(iniUri, out resopnseStream);
            //GetRequest(@"https://kyfw.12306.cn/otn/dynamicJs/loginJs", out resopnseStream);
            // return check code picture.
            string uri = "https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand";
            //string uri = "https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=login&rand=sjrand";
            if (HttpStatusCode.OK == GetRequest(uri, out resopnseStream))
            {
                Stream chkcodestream = resopnseStream;
                checkCodeImage.Image = Image.FromStream(chkcodestream);
            }
            else
            {
                checkCodeImage.Image = null;
                retLbl.Text = "Get CheckCode failed.";
            }
        }

        private void loginBtn_Click(object sender, EventArgs e)
        {
            string uri = @"https://kyfw.12306.cn/otn/login/loginAysnSuggest";
            string userName = usernameTB.Text.Trim();
            string psw = pswTB.Text.Trim();
            string chkCode = chkCodeTB.Text.Trim();
            string data = string.Format("loginUserDTO.user_name={0}&userDTO.password={1}&randCode={2}", userName, psw, chkCode);
            Stream responseStream;
            if (HttpStatusCode.OK == PostRequest(uri, data, out responseStream))
            {
                StreamReader sr = new StreamReader(responseStream);
                string str = sr.ReadToEnd();
                var loginRet = JsonConvert.DeserializeObject<LoginResult>(str);
                if (loginRet.data.loginCheck == "Y")
                {
                    string name = GetRealName();
                    if (!string.IsNullOrEmpty(name))
                    {
                        welcome.Text = "Hello, " + name;
                        welcome.ForeColor = Color.Blue;
                        loginBtn.Enabled = false;
                        usernameTB.Clear();
                        pswTB.Clear();
                        chkCodeTB.Clear();
                        button1.Enabled = false;

                        retLbl.Text = "Log in sucessfully.";
                        retLbl.ForeColor = Color.Green;
                    }
                }
                else
                {
                    retLbl.Text = "Log in failed.";
                    retLbl.ForeColor = Color.Red;
                }
            }
            else
            {
                retLbl.Text = "Log in failed.";
                retLbl.ForeColor = Color.Red;
            }
        }

        private string GetRealName()
        {
            string name = string.Empty;
            string uri = @"https://kyfw.12306.cn/otn/modifyUser/initQueryUserInfo";
            Stream resopnseStream;
            if (HttpStatusCode.OK == GetRequest(uri, out resopnseStream))
            {
                StreamReader sr = new StreamReader(resopnseStream);
                string output = sr.ReadToEnd();
                sr.Close();
                string pat = @"用户名：</span>[^>]*>(?<name>[^<]*)</div>";
                Regex reg = new Regex(pat);
                var matches = reg.Matches(output);
                if (matches.Count > 0)
                {
                    foreach (Match match in matches)
                    {
                        name += "/" + match.Groups["name"].Value.ToString();
                    }
                }
            }
            return name.Length > 0 ? name.Substring(1) : string.Empty;
        }

        // return the response's body of the uri by GET method.
        private HttpStatusCode GetRequest(string uri, out Stream responseStream)
        {

            CookieContainer cc = new CookieContainer();
            foreach (var key in SessionCookies.Keys)
            {
                cc.Add(new Uri(uri), new Cookie(key, SessionCookies[key]));
            }

            HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
            request.Method = "GET";
            request.KeepAlive = true;
            request.Headers.Set("DNT", "1");
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";
            request.CookieContainer = cc;
            // 提交请求数据  
            HttpWebResponse response;
            // Get response body.
            response = request.GetResponse() as HttpWebResponse;
            responseStream = response.GetResponseStream();
            return response.StatusCode;
        }

        private HttpStatusCode PostRequest(string uri, string data, out Stream responseStream)
        {
            CookieContainer cc = new CookieContainer();
            foreach (var key in SessionCookies.Keys)
            {
                cc.Add(new Uri(uri), new Cookie(key, SessionCookies[key]));
            }

            // 将提交的字符串数据转换成字节数组  
            byte[] postData = Encoding.UTF8.GetBytes(data);
            // 设置提交的相关参数  
            HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
            Encoding myEncoding = Encoding.GetEncoding("gb2312");
            request.Method = "POST";
            request.KeepAlive = true;
            request.Headers.Set("DNT", "1");
            request.Headers.Set("X-Requested-With", "XMLHttpRequest");
            request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
            request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";
            request.CookieContainer = cc;
            request.ContentLength = postData.Length;
            // 提交请求数据  
            System.IO.Stream outputStream = request.GetRequestStream();
            outputStream.Write(postData, 0, postData.Length);
            outputStream.Close();
            HttpWebResponse response;
            //Stream responseStream;
            //StreamReader reader;
            response = request.GetResponse() as HttpWebResponse;
            responseStream = response.GetResponseStream();
            return response.StatusCode;
        }

        private void queryBtn_Click(object sender, EventArgs e)
        {
            string uri = @"https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2014-01-23&leftTicketDTO.from_station=SHH&leftTicketDTO.to_station=HFH&purpose_codes=ADULT";

            Stream responseStream;
            if (HttpStatusCode.OK == GetRequest(uri, out responseStream))
            {
                StreamReader sr = new StreamReader(responseStream);
                string str = sr.ReadToEnd();
                var queryRet = JsonConvert.DeserializeObject<QueryTicketResult>(str);
                if (queryRet.data != null && queryRet.data.Count > 0)
                {
                    listView1.View = View.Details;
                    listView1.GridLines = true;
                    //listView1.HeaderStyle = ColumnHeaderStyle.Nonclickable;
                    listView1.Columns.Add("车次", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("起始站", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("到达站", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("起始时间", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("历时", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("商务座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("特等座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("一等座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("二等座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("高级软卧", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("软卧", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("硬卧", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("硬座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("无座", 60, HorizontalAlignment.Right);
                    listView1.Columns.Add("其他", 60, HorizontalAlignment.Right);
                    listView1.Visible = true;

                    foreach (OneTicketItem d in queryRet.data)
                    {
                        var t = d.queryLeftNewDTO;
                        ListViewItem item = new ListViewItem(
                            new string[] { 
                                t.station_train_code, 
                                t.start_station_name, 
                                t.to_station_name, 
                                t.start_time, t.lishi, 
                                t.swz_num,  // 商务座
                                t.tz_num,   // 特等座
                                t.zy_num,   // 一等座
                                t.ze_num,   // 二等座
                                t.gr_num,   // 高级软卧
                                t.rw_num,   // 软卧
                                t.yw_num,   // 硬卧
                                t.yz_num,   // 硬座
                                t.wz_num,   // 无座
                                t.qt_num    // 其他
                                });
                        listView1.Items.Add(item);
                    }
                }

            }
            else
            {
                retLbl.Text = "Query Ticket failed.";
            }
        }

        private void chkCodeTB_Leave(object sender, EventArgs e)
        {

        }

        private void GetCookies()
        {
            List<string> uris = new List<string>() { @"https://kyfw.12306.cn/otn" };
            //List<string> uris = new List<string>() { @"https://kyfw.12306.cn/otn", @"https://kyfw.12306.cn/otn/" };
            foreach (var uri in uris)
            {
                HttpWebRequest request;
                CookieContainer cc = new CookieContainer();
                foreach (var key in SessionCookies.Keys)
                {
                    cc.Add(new Uri(uri), new Cookie(key, SessionCookies[key]));
                }
                request = WebRequest.Create(uri) as HttpWebRequest;
                request.CookieContainer = cc;
                request.Method = "GET";
                request.KeepAlive = true;
                request.Accept = "text/html, application/xhtml+xml, */*";
                request.Referer = "http://www.12306.cn/mormhweb/";
                request.Host = "kyfw.12306.cn";
                request.Headers.Set("DNT", "1");
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko";
                // Get response body.
                HttpWebResponse response;
                response = request.GetResponse() as HttpWebResponse;
                List<string> cookies = response.Headers.Get("Set-Cookie").Split(",".ToCharArray()).ToList();
                cookies.Add(request.Headers.Get("Cookie"));
                foreach (var cookie in cookies)
                {
                    string pat = "(?<key>^[^=]+)=(?<value>[^;]+)";
                    Regex reg = new Regex(pat);
                    Match match = reg.Match(cookie);
                    if (match.Success)
                    {
                        SessionCookies[match.Groups["key"].ToString()] = match.Groups["value"].Value.ToString();
                    }
                }
            }
        }
    }
}
